/*
  创建一个Promise
  1. Promise 就是一个类 在执行这个类的时候 需要传递一个执行器进去 执行器会立即执行
  2. Promise 中有三种状态 分别为 成功 fulfilled 失败 rejected 等待 pending
  pending => fulfilled
  penging => rejected
  3. resolve和reject函数是用来更改状态的
    resolve: fulfilled
    rejected: rejected
  4. then方法内部做的事情就是判断状态 如果状态是成功，就调用成功的方法，如果状态是失败，就调用失败的方法，
    每个promise对象都能调用then方法，所以then方法应该是定义在原型对象上的
  5. then成功回调有一个参数 表成功之后的值 then失败回调也有一个参数 表失败后的原因
  7. then方法是可以被链式调用的，后面的then方法的回调函数拿到值的是上一个then方法的回调函数的返回值
*/
// let promise = new Promise((resolve, reject) => {
//   // 传递给resolve和reject的参数，就是成功之后的值，失败的原因
//   resolve('success') // success就是 成功之后的值
//   reject('fail')  // fail就是 失败的原因
// })
// promise.then(() => {}, () => {})
// promise.then(value => {}, err => {})

const MyPromise = require('./myPromise')

// 1. 没有调用异步代码的情况
let promise = new MyPromise((resolve, reject) => {
  // 传递给resolve和reject的参数，就是成功之后的值，失败的原因
  resolve('success') // success就是 成功之后的值
  // reject('fail')  // fail就是 失败的原因
})
promise.then(() => {}, () => {})
promise.then(value => {
  console.log(value)
}, err => {
  console.log(err)
})

// 2. 处理异步处理的情况
let p = new MyPromise((resolve, reject) => {
  setTimeout(() => {
    resolve('success 2000') // success就是 成功之后的值
  }, 2000)
})
p.then(value => {
  console.log(value)
}, err => {
  console.log(err)
})

// 3. then方法的链式调用，then方法值的传递
/*
思路：
1. then方法是被Promise调用的，要想then方法能被链式调用，那就是then方法返回的也是一个Promise
2. then方法的第一个参，其实就是调用的resolve方法，如果想要上一个Promise的返回值，作为下一个then方法参数，就是把返回值传给resolve即可
  即resolve(100)
3. 判断promise返回的值是普通值，还是一个promise，如果返回的是promise就继续把参数传入，进行then方法的调用
*/
// 返回值为 普通值的情况
let p1 = new MyPromise((resolve, reject) => {
  resolve('成功')
})
p1.then(value => {
  console.log(value)
  return 100
}).then(value => {
  console.log(value)
})
// 返回值为promise的情况
function other() {
  return new MyPromise((resolve, reject) => {
    resolve('other')
  })
}
p1.then(value => {
  console.log(value)
  return other()
}).then(value => {
  console.log(value)
})
// 返回值为promise自己本身的情况
let p02 = new MyPromise((resolve, reject) => {
  resolve('-------这是promise返回自己本身的过渡线-----')
})
let p2 = p02.then(value => {
  console.log(value)
  return p2
})

p2.then(value => {
  console.log(value)
}, reason => {
  console.log(reason.message)
})

// 4. 错误异常处理
// a. 执行器错误
let p4 = new MyPromise((resolve, reject) => {
  throw new Error('executor error')
})
// 在then的第二参数里捕获错误
p4.then(value => {
  console.log('------这是第四点错误异常处理分割线-----')
  console.log(value)
}, reason => {
  console.log(reason.message)
})
// 捕获在then的第一个参数回调函数的错误，是在第二个then方法的第二个参数里面才能获取到错误
let p41 = new MyPromise((resolve, reject) => {
  // throw new Error('executor error')
  resolve('------捕获在then的第一个参数回调函数的错误-----')
})
p41.then(value => {
  console.log(value)
  throw new Error('then error')
}, reason => {
  console.log(reason.message)
}).then(value => {
  console.log(value)
}, reason => {
  console.log('---判断是否在第二个then里获取到错误')
  console.log(reason.message)
})
// 捕获 reject异常
let p42 = new MyPromise((resolve, reject) => {
  // throw new Error('executor error')
  reject('------失败捕获-----')
})
p42.then(value => {
  console.log(value)
}, reason => {
  console.log(reason)
  return 1000
}).then(value => {
  console.log('获取上一个Promise 失败后的异常 return 正常，是在下一个then方法的第一个回调函数里获取')
  console.log(value)
})
// 异步代码的错误异常捕获
let p43 = new MyPromise((resolve, reject) => {
  setTimeout(() => {
    resolve('异步代码的成功。。。。。')
  }, 2000)
})
p43.then(value => {
  console.log(value)
  return 'aaaaaaaaa'
}, reason => {
  console.log(reason)
  return 1000000
}).then(value => {
  console.log(value)
})

// all方法的实现调用
function pp1() {
  return new MyPromise(function(resolve, reject) {
    setTimeout(function() {
      resolve('pp1')
    }, 2000)
  })
}
function pp2() {
  return new MyPromise(function(resolve, reject) {
    // resolve('pp2')
    reject('失败')
  })
}
MyPromise.all(['a', 'b', pp1(), pp2(), 'c']).then(result => console.log(result))

// resolve方法的实现调用
MyPromise.resolve(100).then(value => console.log(value))
MyPromise.resolve(pp1()).then(value => console.log(value))

// finally方法的实现调用
pp2().finally(() => {
  console.log('finally')
  return pp1()
}).then(value => {
  console.log(value, '====finally resolve')
}, reason => {
  console.log(reason, '=====finally reject')
})

// catch方法的实现调用
// pp2().then(value => console.log(value)).catch(reason => console.log(reason))